/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.baiyu.netty;


import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import com.baiyu.model.*;
import com.baiyu.model.base.Message;
import com.ruoyi.common.utils.JsonEnumUtil;
import com.ruoyi.common.utils.R;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;


import java.util.HashMap;
import java.util.Map;

/**
 * Echoes uppercase content of text frames.
 */
@Slf4j
@Component
@Scope("prototype")
@ChannelHandler.Sharable
public class MocWebSocketFrameHandler extends SimpleChannelInboundHandler<Message> {

    @Value("${uploadPath}")
    private String uploadPath;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message frame) throws Exception {
        if (frame instanceof SendMsgToUser) {
            log.debug("收到------SendMsgToUser----消息--------");
            SendMsgToUser model = ((SendMsgToUser) frame);
            ctx.channel().writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(model)));
        } else if (frame instanceof SendMsgToHouse) {
            log.debug("收到------SendMsgToHouse----消息--------");
            SendMsgToHouse model = ((SendMsgToHouse) frame);
            ctx.channel().writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(model)));
        } else if (frame instanceof SendMsgToAll) {
            log.debug("收到------SendMsgToAll----消息--------");
            SendMsgToAll model = ((SendMsgToAll) frame);
            ctx.channel().writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(model)));
        } else if (frame instanceof SendBinaryToUser) {
            log.debug("收到------SendBinaryToUser----消息--------");
            doSendBinaryToUserBussiness(ctx, (SendBinaryToUser) frame);
        } else if (frame instanceof SendBinaryToHouse) {
            log.debug("收到------SendBinaryToHouse----消息--------");
            SendBinaryToHouse model = ((SendBinaryToHouse) frame);
            if (model.getFormat() == FormatType.IMAGE_PNG) {
                NewMsg newMsg = new NewMsg();
                newMsg.setFormat(FormatType.IMAGE_PNG);
                newMsg.setContent(model.getContent());
                ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonEnumUtil.toStr(newMsg)));
            }
        } else if (frame instanceof SendBinaryToAll) {
            log.debug("收到------SendBinaryToAll----消息--------");
            SendBinaryToAll model = ((SendBinaryToAll) frame);
            ctx.channel().writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(model)));
        } else if (frame instanceof InitUser) {
            log.debug("收到------InitUser----消息--------");
            InitUser model = ((InitUser) frame);
        }
    }

    /**
     * SendBinaryToUser的商务方法
     *
     * @param ctx
     * @param frame
     */
    private void doSendBinaryToUserBussiness(ChannelHandlerContext ctx, SendBinaryToUser frame) {
        int chat_type = 0;
        SendBinaryToUser model = frame;
        String tableName = "t_forum_message";
        Map<String, Object> data = new HashMap<>();
        Map<String, Object> params = new HashMap<>();
        params.put("tableName", tableName);
        params.put("data", data);
        data.put("receiver_id", model.getReceiveId());
        data.put("sender_id", model.getSenderId());
        String type = model.getFormat().getValue();
        type = type.substring(0, type.lastIndexOf("/")).replace("image", "img");
        data.put("type", type);
        byte[] bytes = Base64.decode(frame.getContent());
        String uri = "/forum_message/" + frame.getSenderId() + "_" + frame.getReceiveId() + "/" + System.currentTimeMillis() + ".0";
        String filePath = uploadPath + uri;
        FileUtil.writeBytes(bytes, filePath);
        data.put("content", filePath);
        data.put("chat_type", chat_type);

        NewMsg newMsg = new NewMsg();
        newMsg.setFormat(model.getFormat());
        newMsg.setContent(uri);
        //发送
        ChannelHandlerContext toctx = null;
        if(toctx==null){
            newMsg.setData(R.offline());
            ctx.channel().writeAndFlush(newMsg);
        }else{
            newMsg.setData(R.success());
            ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonEnumUtil.toStr(newMsg)));
            toctx.channel().writeAndFlush(new TextWebSocketFrame(JsonEnumUtil.toStr(newMsg)));
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                log.debug("30秒没有读到要websocket网页客户端的信息读空闲，主动断开连接---{}", ctx);
                ctx.close();
                return;
            } else if (event.state() == IdleState.WRITER_IDLE) {
                log.debug("发送心跳包websocket---");
                ctx.writeAndFlush(new PingWebSocketFrame());
            }
        } else if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            //这里可以处理与硬件通信两个管道对接,握手完成

        }
        // 非空闲事件，传递给下一个处理器
        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        log.debug("--------websocket-------读完成了-----------------{}", ctx);
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.debug("--------websocket-------发生异常-----------------", cause);
        ctx.close();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.debug("--------websocket--------关闭连接---------------{}", ctx);
        super.channelInactive(ctx);
    }
}
